/**
 * 
 */
package cn.springsoter.core.security.serializer;

import java.io.IOException;
import java.util.Objects;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;

import cn.springsoter.core.security.annotation.SensitiveInfo;
import cn.springsoter.core.security.enums.SensitiveTypeEnum;
import cn.springsoter.core.security.utils.SensitiveInfoUtil;

/**
 * 脱敏序列化类（简单型）
 * 
 * @author kevin
 *
 */
public class SensitiveInfoSerialize extends JsonSerializer<String> implements ContextualSerializer {

	private SensitiveTypeEnum type;
	private boolean useCustom;
	private int keepLeft;
	private int keepRight;

	public SensitiveInfoSerialize() {
	}

	public SensitiveInfoSerialize(final SensitiveTypeEnum type, final boolean useCustom, final int keepLeft, final int keepRight) {
		this.type = type;
		this.useCustom = useCustom;
		this.keepLeft = keepLeft;
		this.keepRight = keepRight;
	}

	@Override
	public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider,
			final BeanProperty beanProperty) throws JsonMappingException {
		if (beanProperty != null) { // 为空直接跳过
			if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { // 非 String 类直接跳过
				SensitiveInfo sensitiveInfo = beanProperty.getAnnotation(SensitiveInfo.class);
				if (Objects.isNull(sensitiveInfo)) {
					sensitiveInfo = beanProperty.getContextAnnotation(SensitiveInfo.class);
				} 
				if(Objects.nonNull(sensitiveInfo)) {
					// 如果能得到注解，就将注解的 value 传入 SensitiveInfoSerialize
					return new SensitiveInfoSerialize(sensitiveInfo.value(), sensitiveInfo.useCustom(), sensitiveInfo.keepLeft(), sensitiveInfo.keepRight());
				}
			}
			return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
		}
		return serializerProvider.findNullValueSerializer(beanProperty);
	}

	@Override
	public void serialize(final String s, final JsonGenerator jsonGenerator,
			final SerializerProvider serializerProvider) throws IOException {
		switch (this.type) {
		case CHINESE_NAME: {
			if(useCustom) {
				jsonGenerator.writeString(SensitiveInfoUtil.chineseName(s, keepLeft, keepRight));
			} else {
				jsonGenerator.writeString(SensitiveInfoUtil.chineseName(s, 0, 1));
			}
			break;
		}
		case ID_CARD: {
			if(useCustom) {
				jsonGenerator.writeString(SensitiveInfoUtil.idCardNum(s, keepLeft, keepRight));
			} else {
				jsonGenerator.writeString(SensitiveInfoUtil.idCardNum(s, 1, 1));
			}
			break;
		}
		case FIXED_PHONE: {
			if(useCustom) {
				jsonGenerator.writeString(SensitiveInfoUtil.fixedPhone(s, keepLeft, keepRight));
			} else {
				jsonGenerator.writeString(SensitiveInfoUtil.fixedPhone(s, 0, 4));
			}
			break;
		}
		case MOBILE_PHONE: {
			if(useCustom) {
				jsonGenerator.writeString(SensitiveInfoUtil.mobilePhone(s, keepLeft, keepRight));
			} else {
				jsonGenerator.writeString(SensitiveInfoUtil.mobilePhone(s, 3, 2));
			}
			break;
		}
		case ADDRESS: {
			if(useCustom) {
				jsonGenerator.writeString(SensitiveInfoUtil.address(s, keepLeft, keepRight));
			} else {
				jsonGenerator.writeString(SensitiveInfoUtil.address(s, 6, 0));
			}
			break;
		}
		case EMAIL: {
			if(useCustom) {
				jsonGenerator.writeString(SensitiveInfoUtil.email(s, keepLeft, keepRight));
			} else {
				jsonGenerator.writeString(SensitiveInfoUtil.email(s, 1, 0));
			}
			break;
		}
		case BANK_CARD: {
			if(useCustom) {
				jsonGenerator.writeString(SensitiveInfoUtil.bankCard(s, keepLeft, keepRight));
			} else {
				jsonGenerator.writeString(SensitiveInfoUtil.bankCard(s, 0, 4));
			}
			break;
		}
		case CNAPS_CODE: {
			if(useCustom) {
				jsonGenerator.writeString(SensitiveInfoUtil.cnapsCode(s, keepLeft, keepRight));
			} else {
				jsonGenerator.writeString(SensitiveInfoUtil.cnapsCode(s, 2, 0));
			}
			break;
		}
		case NONE: {
			jsonGenerator.writeString(s);
			break;
		}
		}
	}

}
